package com.guandi.geekbrowser.primary.service.impl;

import com.guandi.geekbrowser.primary.entity.Details;
import com.guandi.geekbrowser.primary.repository.DetailsRepository;
import com.guandi.geekbrowser.primary.service.DetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.util.List;
import java.util.Optional;

@Service
public class DetailsServiceImpl implements DetailsService {

    @Autowired
    private DetailsRepository detailsRepository;

    @Override
    public List<Details> findAll() {
        return detailsRepository.findAll();
    }

    @Override
    public void saveDetails(Details details) {
        detailsRepository.saveAndFlush(details);
    }

    @Override
    public void saveDetailList(List<Details> detailsList) {
        detailsRepository.saveAll(detailsList);
    }

    @Override
    public List<Details> findByTabName(String name) {
        return detailsRepository.findByTabName(name);
    }

    @Override
    public List<Details> findByTabNameAndUserId(String name, String id) {
        return detailsRepository.findByTabNameAndUserId(name, id);
    }

    @Override
    public Optional<Details> findById(Long detailId) {
        return detailsRepository.findById(detailId);
    }

    @Override
    public Details findByIdAndUserId(Long detailId, String id) {
        return detailsRepository.findByIdAndUserId(detailId, id);
    }

    @Override
    public Integer deleteAllByTabNameAndUserId(String tabName, String userId) {
        return detailsRepository.deleteAllByTabNameAndUserId(tabName, userId);
    }

    @Override
    public Integer deleteByIdAndUserId(Long id, String userId) {
       return detailsRepository.deleteByIdAndUserId(id, userId);
    }

    @Override
    public void updateOne(String name, Long id,String userId) {
        detailsRepository.updateOne(name, id,userId);
    }

    @Override
    public List<Details> findByRegIp(String ip) {
        return detailsRepository.findByRegIp(ip);
    }

    @Override
    public Details findByIdAndUserIdQuery(Long detailId, String id) {
        return detailsRepository.findByIdAndUserIdQuery(detailId, id);
    }

    @Override
    public List<Details> findByTabNameAndUserIdQuery(String tabName, String UserId) {
        return detailsRepository.findByTabNameAndUserIdQuery(tabName, UserId);
    }

    @Override
    public Integer updateRegister(Long id, boolean register) {
        return detailsRepository.updateRegister(id, register);
    }

    @Override
    public Integer updatePassword(Long id, String password,String uid) {
        return detailsRepository.updatePassword(id, password, uid);
    }

    @Override
    public Integer updatePcCookie(Long id, String pcCookie,String uid) {
        return detailsRepository.updatePcCookie(id, pcCookie,uid);
    }

    @Override
    public Page<Details> findAllPageByTabNameAndUserId(String tabName,String userId,int pageNumber,int pageSize) {
        Pageable pageable = PageRequest.of(pageNumber-1, pageSize);
        Specification<Details> spe = new Specification<Details>() {
            @Override
            public Predicate toPredicate(Root<Details> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<String> name = root.get("tabName");
                Path<String> id = root.get("userId");
                Predicate namePre = criteriaBuilder.equal(name, tabName);
                Predicate idPre = criteriaBuilder.equal(id, userId);
                Predicate predicate = criteriaBuilder.and(namePre, idPre);
                return predicate;
            }
        };
        return detailsRepository.findAll(spe,pageable);
    }

    @Override
    public Page<Details> findAllPageByTabNameAndUserIdAndCountry(String tabName, String userId, int pageNumber, int pageSize, String country,String searchWord,Integer type) {
        Pageable pageable = PageRequest.of(pageNumber-1, pageSize);
        Specification<Details> spe = new Specification<Details>() {
            @Override
            public Predicate toPredicate(Root<Details> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<String> name = root.get("tabName");
                Path<String> countryPath = root.get("country");
                Path<String> id = root.get("userId");
                Path<String> account = root.get("account");
                Path<Integer> typePath = root.get("type");
                Predicate idPre = criteriaBuilder.equal(id, userId);
                Predicate namePre = criteriaBuilder.equal(name, tabName);
                Predicate typePre = criteriaBuilder.equal(typePath, type);
                Predicate countryPre = criteriaBuilder.equal(countryPath, country);
                Predicate like = criteriaBuilder.like(account, "%" + searchWord + "%");
                Predicate predicate = criteriaBuilder.and(namePre, idPre,countryPre,like,typePre);
                return predicate;
            }
        };
        return detailsRepository.findAll(spe,pageable);
    }

    @Override
    public void deleteAll(List<Details> details) {
        detailsRepository.deleteAll(details);
    }

    @Override
    public List<Details> findByUserId(String userId) {
        return detailsRepository.findByUserId(userId);
    }

    @Override
    public Page<Details> findByUserIdQuery(String userId, int pageSize, int pageNumber) {
        Pageable pageable = PageRequest.of(pageNumber-1, pageSize);
        Specification<Details> spe = new Specification<Details>() {
            @Override
            public Predicate toPredicate(Root<Details> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<String> id = root.get("userId");
                Predicate idPre = criteriaBuilder.equal(id, userId);
                Path<String> passwordPath = root.get("password");
                Predicate password = criteriaBuilder.isNotNull(passwordPath);
                Predicate predicate = criteriaBuilder.and(idPre,password);
                return predicate;
            }
        };
        return detailsRepository.findAll(spe,pageable);
    }

    @Override
    public List<Details> findByTabNameAndUserIdAndCountryQuery(String tabName, String UserId, String country) {
        return detailsRepository.findByTabNameAndUserIdAndCountryQuery(tabName, UserId, country);
    }

    @Override
    public List<Details> findByRegIpAndCountry(String ip, String country) {
        return detailsRepository.findByRegIpAndCountry(ip, country);
    }

    @Override
    public Details findByIdAndUserIdAndCountry(Long detailId, String id, String country) {
        return detailsRepository.findByIdAndUserIdAndCountry(detailId, id, country);
    }

    @Override
    public List<Details> findByUserIdAndCountry(String id, String country) {
        return detailsRepository.findByUserIdAndCountry(id,country);
    }

    @Override
    public List<Details> findByUserIdAndCountryQuery(String id, String country) {
        return detailsRepository.findByUserIdAndCountryQuery(id, country);
    }

    @Override
    public Integer deleteAllByTabNameAndUserIdAndCountry(String tabName, String userId, String country) {
        return detailsRepository.deleteAllByTabNameAndUserIdAndCountry(tabName, userId, country);
    }

    @Override
    public List<Details> findByUserIdAndCountryAndType(String id, String country, Integer type) {
        return detailsRepository.findByUserIdAndCountryAndType(id, country, type);
    }
}
